#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "lcd.h"
#include "gps.h"
#include "24l01.h"

#include "FreeRTOS.h"
#include "task.h"
/************************************************
 ALIENTEK 探索者STM32F407开发板 FreeRTOS实验6-1
 FreeRTOS任务创建和删除(动态方法)-库函数版本
 技术支持：www.openedv.com
 淘宝店铺：http://eboard.taobao.com 
 关注微信公众平台微信号："正点原子"，免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者：正点原子 @ALIENTEK
************************************************/

//编译开关
#define USE_LCD
#define USE_USART

//由于51单片机为Big-Endian,而STM32为Little-Endian
//故定义宏如下,以实现转换
#define BE_TO_LE_16(A)	((((u16)(A) & 0xff00) >> 8) | (((u16)(A) & 0x00ff) << 8))
#define BE_TO_LE_32(A)	((((u32)(A) & 0xff000000) >> 24) | \
												 (((u32)(A) & 0x00ff0000) >>  8) | \
												 (((u32)(A) & 0x0000ff00) <<  8) | \
												 (((u32)(A) & 0x000000ff) << 24))                                               

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define TASK1_TASK_PRIO		2
//任务堆栈大小	
#define TASK1_STK_SIZE 		128  
//任务句柄
TaskHandle_t Task1Task_Handler;
//任务函数
void task1_task(void *pvParameters);

//任务优先级
#define TASK2_TASK_PRIO		3
//任务堆栈大小	
#define TASK2_STK_SIZE 		128  
//任务句柄
TaskHandle_t Task2Task_Handler;
//任务函数
void task2_task(void *pvParameters);

//LCD显示函数
#ifdef USE_LCD
void dispGPS(void);
#endif

//串口传输函数
#ifdef USE_USART
void printGPSFrame(void);
#endif

//LCD刷屏时使用的颜色
int lcd_discolor[14]={	WHITE, BLACK, BLUE,  BRED,      
						GRED,  GBLUE, RED,   MAGENTA,       	 
						GREEN, CYAN,  YELLOW,BROWN, 			
						BRRED, GRAY };

//缓存接收到的GPS定位信息 
uint8_t tmp_buf[20] = {0};

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	delay_init(168);					//初始化延时函数
	uart_init(115200);     				//初始化串口
	LED_Init();		        			//初始化LED端口
	LCD_Init();							//初始化LCD
	NRF24L01_Init();    //初始化NRF24L01
	
	POINT_COLOR=RED;    //画笔颜色：红色
	while(NRF24L01_Check())
	{
		LCD_ShowString(30,130,200,16,16,(u8*)("NRF24L01 Error"));
		delay_ms(200);
		LCD_Fill(30,130,239,130+16,WHITE);
 		delay_ms(200);
	}
	LCD_ShowString(30,130,200,16,16,(u8*)("NRF24L01 OK")); 	 
  
	LCD_Clear(WHITE);//清屏，不然显示不下
	
    NRF24L01_RX_Mode();
 	POINT_COLOR=BLUE;//设置字体为蓝色	   
    LCD_ShowString(10,0,200,16,16,(u8*)("NRF24L01 RX_Mode"));
    LCD_ShowString(10,20,200,16,16,(u8*)("Received DATA:"));
    
	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,             
                (const char*    )"task1_task",           
                (uint16_t       )TASK1_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )TASK1_TASK_PRIO,        
                (TaskHandle_t*  )&Task1Task_Handler);   
    //创建TASK2任务
    xTaskCreate((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler); 
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//task1任务函数
void task1_task(void *pvParameters)
{
	u8 task1_num=0;
	
	while(1)
	{
		task1_num++;	//任务执1行次数加1 注意task1_num1加到255的时候会清零！！
		LED0=!LED0;
		//printf("任务1已经执行：%d次\r\n",task1_num);
        
#ifdef USE_LCD
        dispGPS();
#endif
        
        vTaskDelay(200);                           //延时100ms
	}
}

//task2任务函数
void task2_task(void *pvParameters)
{
	u8 task2_num=0;
	
	while(1)
	{
		task2_num++;	//任务2执行次数加1 注意task1_num2加到255的时候会清零！！
        LED1=!LED1;
		//printf("任务2已经执行：%d次\r\n",task2_num);
        if(NRF24L01_RxPacket(tmp_buf) == 0)
        {
            
#ifdef USE_USART            
            printGPSFrame();
#endif
        }
        vTaskDelay(20);                           //延时20ms	
	}
}

//LCD显示函数
#ifdef USE_LCD
NMEA_MSG nmea_msg;

void dispGPS(void)
{
    static uint8_t t = 0;
    NMEA_MSG *nmea_msg_p;
    
    nmea_msg_p = (NMEA_MSG*)tmp_buf;

    nmea_msg.utc.hour = (*nmea_msg_p).utc.hour;
    nmea_msg.utc.min = (*nmea_msg_p).utc.min;
    nmea_msg.utc.sec = (*nmea_msg_p).utc.sec;
    nmea_msg.latitude = BE_TO_LE_32((*nmea_msg_p).latitude);
    nmea_msg.nshemi = (*nmea_msg_p).nshemi;
    nmea_msg.longitude = BE_TO_LE_32((*nmea_msg_p).longitude);
    nmea_msg.ewhemi = (*nmea_msg_p).ewhemi;
    nmea_msg.gpssta = (*nmea_msg_p).gpssta;
    nmea_msg.posslnum = (*nmea_msg_p).posslnum;
    nmea_msg.hdop = BE_TO_LE_16((*nmea_msg_p).hdop);
    nmea_msg.altitude.sign = (*nmea_msg_p).altitude.sign;
    nmea_msg.altitude.value = BE_TO_LE_16((*nmea_msg_p).altitude.value);
    
    if(t == 0)
    {
        LCD_Fill(0,40,239,200,WHITE);
        POINT_COLOR = RED;
        LCD_ShowString(15,40,200,16,16,(u8*)("Time:"));
        LCD_ShowString(15,60,200,16,16,(u8*)("Latitude:"));
        LCD_ShowString(15,100,200,16,16,(u8*)("Longitude:"));
        LCD_ShowString(15,140,200,16,16,(u8*)("GPS Status:"));
        LCD_ShowString(15,200,200,16,16,(u8*)("Posslnum:"));
        LCD_ShowString(15,180,200,16,16,(u8*)("Hdop:"));
        LCD_ShowString(15,280,200,16,16,(u8*)("Altitude:"));
    }
    
    if(++t == 200)	//大约每隔10s清一次屏,视无线传输频率而定
    {
        t = 0;
    }
   
    POINT_COLOR = BLUE;
    LCD_ShowxNum(65,40,nmea_msg.utc.hour,2,16,0x80);
    LCD_ShowChar(81,40,':',16,0);
    LCD_ShowxNum(89,40,nmea_msg.utc.min,2,16,0x80);
    LCD_ShowChar(105,40,':',16,0);
    LCD_ShowxNum(113,40,nmea_msg.utc.sec,2,16,0x80);

    POINT_COLOR = BLUE;
    LCD_ShowxNum(33,80,nmea_msg.latitude,7,16,0);
    LCD_ShowChar(97,80,' ',16,0);
    LCD_ShowChar(105,80,nmea_msg.nshemi,16,0);

    POINT_COLOR = BLUE;
    LCD_ShowxNum(25,120,nmea_msg.longitude,8,16,0);
    LCD_ShowChar(97,120,' ',16,0);
    LCD_ShowChar(105,120,nmea_msg.ewhemi,16,0);
    
    POINT_COLOR = BLUE;
    switch(nmea_msg.gpssta)
    {
    case 0:
        LCD_ShowString(25,160,200,16,16,(u8*)("Not Locate!")); break;
    case 1:
        LCD_ShowString(25,160,200,16,16,(u8*)("Non-differential!")); break;
    case 2:
        LCD_ShowString(25,160,200,16,16,(u8*)("Differential!")); break;
    case 6:
        LCD_ShowString(25,160,200,16,16,(u8*)("Estimated!")); break;
    default:
        LCD_ShowString(25,160,200,16,16,(u8*)("Data Error!"));						
    }

    POINT_COLOR = BLUE;
    LCD_ShowxNum(25,220,nmea_msg.posslnum,2,16,0);
  
    POINT_COLOR = BLUE;
    LCD_ShowxNum(55,180,nmea_msg.hdop,3,16,0);

    POINT_COLOR = BLUE;
    switch(nmea_msg.altitude.sign)
    {
    case 0:
        LCD_ShowChar(25,300,' ',16,0); break;
    case 1:
        LCD_ShowChar(25,300,'-',16,0); break;
    }
    LCD_ShowxNum(33,300,nmea_msg.altitude.value,5,16,0);
}
#endif

//串口传输函数
#ifdef USE_USART
uint8_t usartFrame[49];

void printGPSFrame(void)
{
    int count;  //单纯的计数变量
    int frameIndex;
    uint8_t usartCheckSum;  //UART数据帧校验和
    
    count = 0;  //单纯的计数变量
    frameIndex = 4;
    usartCheckSum = 0;  //UART数据帧校验和

    //帧定界符 参考xbee模块，详见中文版使用说明page48，长度20字节 0x14
    usartFrame[0] = 0x7e;
    usartFrame[1] = 0x7d;
    usartFrame[2] = 0x20;
    usartFrame[3] = 0x14;
    
    for(count = 0; count < 20; count++)
    {
        usartCheckSum += tmp_buf[count];
        
        if((tmp_buf[count] == 0x7e) || (tmp_buf[count] == 0x7d) || (tmp_buf[count] == 0x00))
        {   
            usartFrame[frameIndex++] = 0x7d;
            usartFrame[frameIndex++] = tmp_buf[count]^0x20;
        }
        else
        {
            usartFrame[frameIndex++] = tmp_buf[count];
        }
    }
    
    usartCheckSum = 0xff - usartCheckSum;   //真正的校验和
    if((usartCheckSum == 0x7e) || (usartCheckSum == 0x7d) || (tmp_buf[count] == 0x00))
    {   
        usartFrame[frameIndex++] = 0x7d;
        usartFrame[frameIndex++] = usartCheckSum^0x20;
    }
    else
    {
        usartFrame[frameIndex++] = usartCheckSum;
    }
    
    usartFrame[frameIndex++] = '\r';
    usartFrame[frameIndex++] = '\n';
    usartFrame[frameIndex] = '\0';
    
    printf("%s", usartFrame);
}

#endif
